#pragma once

#include <iostream>
#include <thread>
#include <mutex>
#include <condition_variable>
#include <queue>
#include <vector>
#include "Log.hpp"
#include "Task.hpp"

#define NUM 4

class ThreadPool
{
private:
    ThreadPool(int num = NUM) : _num(num), _stop(false)
    {
        InitThreadPool();
    }

public:
    static ThreadPool *getinstance()
    {
        static ThreadPool instance; // 线程安全的初始化
        return &instance;
    }

    bool IsStop()
    {
        return _stop;
    }
    bool TaskQueueIsEmpty()
    {
        return _task_queue.empty();
    }

    void ThreadRoutine()
    {
        while (true)
        {
            Task t;
            {
                std::unique_lock<std::mutex> lock(_mtx);
                // 等待任务或终止信号（避免虚假唤醒）
                _cv.wait(lock, [this]
                        { return !_task_queue.empty() || _stop; });

                if (_stop && _task_queue.empty())
                    return; // 终止线程

                t = _task_queue.front();
                _task_queue.pop();
            } // 自动释放锁
            t.ProcessOn();
        }
    }

    bool InitThreadPool()
    {
        for (int i = 0; i < _num; i++)
        {
            _threads.emplace_back([this]
                                 { this->ThreadRoutine(); });
        }
        ILOG("Thread pool created with %d threads", _num);
        return true;
    }

    void PushTask(Task task)
    {
        {
            std::lock_guard<std::mutex> lock(_mtx);
            _task_queue.push(std::move(task));
        }
        _cv.notify_one(); // 通知一个等待线程
    }

    ~ThreadPool()
    {
        {
            std::lock_guard<std::mutex> lock_(_mtx);
            _stop = true; // 设置终止标志
        }
        _cv.notify_all(); // 唤醒所有线程

        for (auto &t : _threads)
        {
            if (t.joinable())
                t.join(); // 等待线程结束
        }
        ILOG("Thread pool destroyed");
    }

    // 删除拷贝构造和赋值
    ThreadPool(const ThreadPool &) = delete;
    ThreadPool &operator=(const ThreadPool &) = delete;

private:
    int _num;
    bool _stop;
    std::queue<Task> _task_queue;
    std::mutex _mtx;
    std::condition_variable _cv;
    std::vector<std::thread> _threads;
};